package com.fit.utils.se;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



/**
 * 时间工具类
 * @author Administrator
 *
 */
public class TimeUtil {
	
	private static Logger log = LoggerFactory.getLogger(TimeUtil.class);
	
	/**
	 * 日期转换格式
	 */
	public final static String Y = "yyyy";
	public final static String YM = "yyyy-MM";
	public final static String YMD = "yyyy-MM-dd";
	public final static String YMDHM = "yyyy-MM-dd HH:mm";
	public final static String YMDHMS = "yyyy-MM-dd HH:mm:ss";
	public final static String YMDHMSS = "yyyy-MM-dd HH:mm:ss.SSS";
	
	/**
	 * 验证此字符是否是指定格式的日期字符串
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static boolean validate(String dateStr,String dateFormat){
		try{
			getDate(dateStr, dateFormat);
			return true;
		}catch(Exception e){
			return false;
		}
	}
	
	/**
	 * 严格的验证日期是否正确(正确返回转换后的字符串，否则返回null)
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static String strictValidateDate(String dateStr,String dateFormat){
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		sdf.setLenient(false);
		try{
			return getDate(sdf.parse(dateStr), dateFormat);
		}catch(ParseException e){
			return null;
		}
	}
	
	
	/**
	 * 通过传入的日期格式获取当前的时间字符串
	 * @param dateFormat
	 * @return
	 */
	public static String getCurrentDate(String dateFormat){
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.format(new Date());
	}
	
	
	
	/**
	 * 通过传入的 日期对象  按照传入的格式转换成对应的日期字符串
	 * @param date
	 * @param dateFormat
	 * @return
	 */
	public static String getDate(Date date,String dateFormat){
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.format(date);
	}
	
	/**
	 * 通过传入的日期字符串 按照传入的格式转换成日期对象
	 * @param date
	 * @param dateFormat
	 * @return
	 */
	public static Date getDate(String dateStr,String dateFormat){
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		Date date = null;
		try{
			date = sdf.parse(dateStr);
		}catch(Exception e){
			log.error("格式化日常异常：{}  不能格式化为  {}",dateStr,dateFormat, e);
		}
		return date;
	}
	
	
	/**
	 * 通过传入的日期字符串 按照传入的格式转换成对应的字符串日期
	 * @param dateStr
	 * @param dateFormat
	 * @param resultDteFormat
	 * @return
	 */
	public static String getDateStr(String dateStr,String dateFormat,String resultDteFormat){
		return getDate(getDate(dateStr, dateFormat), resultDteFormat);
	}

	
	/**
	 * 通过传入的日期日子串及传入的格式   在此日期的基础上加上mobileNumber 的天数或者减去mobileNumber
	 * 在传入日期的基础上加上几天，mobileNumber必须为正整数
	 *  在传入日期的基础上减去几天，mobileNumber必须为负正整数
	 * @param dateStr
	 * @param dateFormat
	 * @param mobileNumber
	 * @return
	 */
	public static String dateMobile(String dateStr,String dateFormat,int mobileNumber){
		String date = null;
		try{
		    Calendar c = Calendar.getInstance();
	        c.setTime(TimeUtil.getDate(dateStr, dateFormat));
	        c.add(Calendar.DAY_OF_MONTH, mobileNumber);
	        date = TimeUtil.getDate(c.getTime(), dateFormat);
		}catch(Exception e){
			log.error("移动天数异常：日期 {}  格式 {}  移动 {}",dateStr,dateFormat,mobileNumber, e);
		}
		return date;
	}
	
	/**
	 * 移动月份
	 * 如传入 2015-02-01  移动 -1   返回 2015-01-01
	 * @param dateStr
	 * @param dateFormat
	 * @param mobileNumber
	 * @return
	 */
	public static String dateMobileMonth(String dateStr,String dateFormat,int mobileNumber){
		try{
		    Calendar c = Calendar.getInstance();
	        c.setTime(TimeUtil.getDate(dateStr, dateFormat));
	        c.add(Calendar.MONTH, mobileNumber);
	        dateStr = TimeUtil.getDate(c.getTime(), dateFormat);
		}catch(Exception e){
			log.error("移动月份异常：日期 {} 格式 {} 移动 {}",dateStr,dateFormat,mobileNumber, e);
		}
		return dateStr;
	}
	
	
	/**
	 * 获取传入时间是星期几,传入日期为null时  默认为当前时间
	 * @return  返回1~7
	 */
	public static int getDateWeek(String dateStr,String dateFormat){
		if(dateStr == null || "".equals(dateStr)){
			dateFormat = TimeUtil.YMD;
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(TimeUtil.getDate(dateStr, dateFormat));
		int num = cal.get(Calendar.DAY_OF_WEEK)-1;
		return num == 0?7:num;
	}
	
	/**
	 * 获取传入日期的 当前月的最后一天， 如果传入日期为null  默认为当前时间
	 * @return  
	 */
	public static String getMonthLastDate(String dateStr,String dateFormat){
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(TimeUtil.getDate(dateStr, dateFormat));
		cal.add(Calendar.MONTH, 1);
		cal.add(Calendar.DAY_OF_MONTH, -1);
		String lastDate = TimeUtil.getDate(cal.getTime(),dateFormat);
		
		return lastDate;
	}
	/**
	 * 获取传入日期的 当前月的第一天 ，如果传入日期为null  默认为当前时间
	 * @return 
	 */
	public static String getMonthFirstDate(String dateStr,String dateFormat){
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(TimeUtil.getDate(dateStr, dateFormat));
		cal.set(Calendar.DAY_OF_MONTH, 1);
		String firstDate = TimeUtil.getDate(cal.getTime(),dateFormat);
		return firstDate;
	}
	
	/**
	 * 通过输入的格式 、日期  获取传入日期的    星期一和 星期天的日期，传入日期为null时默认日期为今天
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static String[] getWeekOneSevenDate(String dateStr,String dateFormat){
		String[] date = new String[2];
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		int num = TimeUtil.getDateWeek(dateStr, dateFormat);
		date[0] = dateMobile(dateStr, dateFormat, (num - num*2) +1);
		
		date[1] = dateMobile(dateStr, dateFormat,  7-num);
		return date;
	}
	
	/**
	 * 通过输入的格式 、日期  获取传入日期的    星期一的日期，传入日期为null时默认日期为今天
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static String getWeekOneDate(String dateStr,String dateFormat){
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		int num = TimeUtil.getDateWeek(dateStr, dateFormat);
		dateStr = dateMobile(dateStr, dateFormat, (num - num*2) +1);
		return dateStr;
	}
	
	/**
	 * 通过输入的格式 、日期  获取传入日期的    星期天的日期，传入日期为null时默认日期为今天
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static String getWeekSevenDate(String dateStr,String dateFormat){
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		int num = TimeUtil.getDateWeek(dateStr, dateFormat);
		dateStr = dateMobile(dateStr, dateFormat,  7-num);
		return dateStr;
	}
	
	
	
	/**
	 * 通过输入的格式 、日期  获取传入日期的  当月第一天和最后一天的日期，传入日期为null时默认日期为今天
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static String[] getMonthFirstLastDate(String dateStr,String dateFormat){
		String[] date = new String[2];
		if(dateStr == null || "".equals(dateStr)){
			dateStr = TimeUtil.getDate(new Date(),dateFormat);
		}
		date[0] = getMonthFirstDate(dateStr, dateFormat);
		date[1] = getMonthLastDate(dateStr, dateFormat);
		return date;
	}
	
	/**
	 * 比较两个日期大小（当date1比date2大时返回1，相等时返回0，date1比date2小时返回-1）
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int comparisonDate(Date date1,Date date2){
		long timeStamp1 = date1.getTime();
		long timeStamp2 = date2.getTime();
		if(timeStamp1 > timeStamp2){
			return 1;
		}else if(timeStamp1 == timeStamp2){
			return 0;
		}else{
			return -1;
		}
	}
	
	
	/**
	 * 如果date1包含在 date2 和 date3之内的话 返回true，否则返回false
	 * date1 大于 date2  并且 date1小于 date3 返回true，否则返回false
	 * @param date1
	 * @param date2
	 * @param date3
	 * @return
	 */
	public static boolean contain(Date date1,Date date2,Date date3){
		int start = TimeUtil.comparisonDate(date1, date2);
		int end = TimeUtil.comparisonDate(date1, date3);
		if(start == 1 && end == -1){
			return true;
		}
		return false;
	}
	
	
	/**
	 * 比较两个日期月份的大小（当date1比date2大时返回1，相等时返回0，date1比date2小时返回-1）
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int comparisonMonth(Date date1,Date date2){
		
		int year1 = getYear(date1);
		int year2 = getYear(date2);
		int month1 = getMonth(date1);
		int month2 = getMonth(date2);
		
		if(year1 > year2){
			return 1;
		}else if(year1 == year2){
			if(month1 > month2){
				return 1;
			}else if(month1 == month2){
				return 0;
			}else{
				return -1;
			}
		}else{
			return -1;
		}
	}
	
	/**
	 * 获取list集合中最大的日期
	 * @param list
	 * @return
	 */
	public static Date getMaxDate(List<Date> list){
		if(list.size() == 0){
			return null;
		}
		Date max = list.get(0);
		for(int i=1; i<list.size(); i++){
			if(TimeUtil.comparisonDate(max, list.get(i)) == -1){
				max = list.get(i);
			}
		}
		return max;
	}
	
	
	/**
	 * 给一个 开始日期和一个结束日期，获取这两个日期之间的日期
	 * 如：2015-05-01   2015-05-31
	 * @return
	 */
	public static List<String> getIntervalDate(String startDate, String endDate){
		
		Date start = getDate(startDate, TimeUtil.YMD);
		Date end = getDate(endDate, TimeUtil.YMD);
		
		String s = getDate(start, TimeUtil.YMD);
		String e = getDate(end, TimeUtil.YMD);
		
		List<String> list = new LinkedList<String>();
		
		int result = TimeUtil.comparisonDate(start, end);
		if(result == 1){
			return list;
		}else if(result == 0){
			list.add(s);
			list.add(e);
			return list;
		}
		
		list.add(s);
		
		while(!s.equals(e)){
			s = dateMobile(s, TimeUtil.YMD, 1);
			list.add(s);
		}
		return list;
	}
	
	/**
	 * 给一个开始月和结束月，获取这两个月之间的所有月份
	 * 如:给一个2015-01-01  2015-03-03
	 * 返回：2015-01  2015-02  2015-03
	 * @param startMonth
	 * @param endMonth
	 * @return
	 */
	public static List<String> getIntervalMonth(String startMonth, String endMonth){
		List<String> list = new LinkedList<String>();
		Date start = getDate(startMonth, TimeUtil.YMD);
		Date end = getDate(endMonth, TimeUtil.YMD);
		String s = getDate(start, TimeUtil.YM);
		String e = getDate(end, TimeUtil.YM);
		int result = TimeUtil.comparisonDate(start, end);
		if(result == 1){
			return list;
		}else if(result == 0){
			list.add(s);
			list.add(e);
			return list;
		}
		list.add(s);
		while(!s.equals(e)){
			s = dateMobileMonth(s, TimeUtil.YM, 1);
			list.add(s);
		}
		return list;
	}
	
	/**
	 * 获取这个日期的 最开始的时间
	 * 如:传入 2015-01-04    返回：2015-01-04 00:00:00
	 * @param dateStr
	 * @return
	 */
	public static String getFirstTime(String dateStr){
		String str = TimeUtil.getDate(TimeUtil.getDate(dateStr, TimeUtil.YMD), TimeUtil.YMD);
		return str + " 00:00:00";
	}
	/**
	 * 获取这个日期 最后的时间
	 * 如:传入 2015-01-04    返回：2015-01-04 23:59:59
	 * @param dateStr
	 * @return
	 */
	public static String getLastTime(String dateStr){
		String str = TimeUtil.getDate(TimeUtil.getDate(dateStr, TimeUtil.YMD), TimeUtil.YMD);
		return str + " 23:59:59";
	}
	
	/**
	 * 获取年份
	 * @param date
	 * @return
	 */
	public static int getYear(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		return year;
	}
	
	/**
	 * 获取月份
	 * @param date
	 * @return
	 */
	public static int getMonth(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int month = cal.get(Calendar.MONTH);
		return month+1;
	}
	
	/**
	 * 获取日
	 * @param date
	 * @return
	 */
	public static int getDay(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int day = cal.get(Calendar.DATE);
		return day;
	}
	/**
	 * 获取时
	 * @param date
	 * @return
	 */
	public static int getHour(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int hour = cal.get(Calendar.HOUR);
		return hour;
	}
	
	/**
	 * 获取分
	 * @param date
	 * @return
	 */
	public static int getMinute(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int minute = cal.get(Calendar.MINUTE);
		return minute;
	}
	/**
	 * 获取秒
	 * @param date
	 * @return
	 */
	public static int getSecond(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int second = cal.get(Calendar.SECOND);
		return second;
	}
	
	/** 
	* 计算两个日期之间相差的天数 
	* @param smdate 较小的时间 
	* @param bdate 较大的时间 
	* @return 相差的天数(没有满一天的自动舍弃)
	*/ 
	public static int daysBetween(String smdate,String bdate, String dateFormat){
		Date smdate1 = getDate(smdate, dateFormat);
		Date bdate2 = getDate(bdate, dateFormat);
		Calendar cal = Calendar.getInstance(); 
		cal.setTime(smdate1); 
		long time1 = cal.getTimeInMillis(); 
		cal.setTime(bdate2); 
		long time2 = cal.getTimeInMillis(); 
		long betweenDays=(time2-time1)/(86400000);//一天 = 1000*3600*24
		return Integer.parseInt(String.valueOf(betweenDays)); 
	}
	
	/** 
	* 计算两个日期之间相差的秒数
	* @param smdate 较小的时间 
	* @param bdate 较大的时间 
	* @return 相差秒数 
	*/ 
	public static long secondsBetween(String smdate,String bdate, String dateFormat){
		Date smdate1 = getDate(smdate, dateFormat);
		Date bdate2 = getDate(bdate, dateFormat);
		Calendar cal = Calendar.getInstance(); 
		cal.setTime(smdate1); 
		long time1 = cal.getTimeInMillis(); 
		cal.setTime(bdate2); 
		long time2 = cal.getTimeInMillis(); 
		long betweenDays=(time2-time1)/(1000);//1000毫秒=1秒
		return betweenDays; 
	}
	
	/** 
	* 计算两个日期之间相差的毫秒数
	* @param smdate 较小的时间 
	* @param bdate 较大的时间 
	* @return 相差毫秒数 
	*/ 
	public static long millisecondsBetween(String smdate,String bdate, String dateFormat){
		Date smdate1 = getDate(smdate, dateFormat);
		Date bdate2 = getDate(bdate, dateFormat);
		Calendar cal = Calendar.getInstance(); 
		cal.setTime(smdate1); 
		long time1 = cal.getTimeInMillis(); 
		cal.setTime(bdate2); 
		long time2 = cal.getTimeInMillis(); 
		long betweenDays=(time2-time1);
		return betweenDays; 
	}
	
	
	/**
	 * 根日期获取时间戳
	 * @param date
	 * @return
	 */
	public static long getTimestamp(Date date){
		return date.getTime();
	}
	
	
	/**
	 * 根据时间获取时间戳
	 * @param dateStr
	 * @param dateFormat
	 * @return
	 */
	public static long getTimestamp(String dateStr,String dateFormat){
		return TimeUtil.getTimestamp(TimeUtil.getDate(dateStr, dateFormat));
	}

	/**
	 * 获取当前时间的时间戳
	 * @return
	 */
	public static long getTimestamp(){
		return System.currentTimeMillis();
	}
	
	/**
	 * 获取当前日期是当前年的第几周
	 * @param dateStr 日期
	 * @param dateFormat 日期格式
	 * @return
	 */
	public static int getWeekNumByYear(String dateStr,String dateFormat){
		Date date = TimeUtil.getDate(dateStr, dateFormat);
		Calendar calendar = Calendar.getInstance();
		calendar.setMinimalDaysInFirstWeek(1);
		calendar.setFirstDayOfWeek(Calendar.MONDAY);
		calendar.setTime(date);
		int weeksNum = calendar.get(Calendar.WEEK_OF_YEAR);
		if(weeksNum == 1 && TimeUtil.getMonth(date) != 1){//不加此句"2016-12-31" 返回为1
			String strd = TimeUtil.getWeekOneDate(dateStr,dateFormat);
			weeksNum = TimeUtil.getWeekNumByYear(TimeUtil.dateMobile(strd, dateFormat, -1), dateFormat) + 1;
		}
		return weeksNum;
	}

}
